﻿using System;
using System.Collections.Generic;
using System.Data.Objects;
using System.Linq;
using System.Linq.Expressions;
using System.Text;

namespace EBA.Data
{
    /// <summary>
    /// 将<see cref="ObjectSet{T}"/>实例包装为<see cref="IQuery{T}"/>对象。
    /// </summary>
    public class EntityQuery<Entity, IEntity> : IQuery<IEntity> where Entity : class,IEntity
    {
        /// <summary>
        /// 原始数据集
        /// </summary>
        public ObjectSet<Entity> Table { get; set; }

        Expression<Func<Entity, bool>> Condition { get; set; }
       

        /// <summary>
        /// 构造函数
        /// </summary>
        public EntityQuery(ObjectSet<Entity> table, Expression<Func<Entity, bool>> condition, params string[] includes)
        {
            this.Table = table;

            this.ObjectQuery = this.Table;

            this.Condition = condition;

            this.Includes = includes ?? new string[] { }; 
        }

        /// <summary>
        /// 查询关联属性的表达式。
        /// </summary>
        protected string[] Includes { get; set; }


        IQueryable<IEntity> _Queryable;

        /// <summary>
        /// 可查询对象
        /// </summary>
        public virtual IQueryable<IEntity> AsQuerybale
        {
            get
            {
                if (this._Queryable == null)
                {
                    this._Queryable = this.TryIncludes(this.ObjectQuery);
                }

                return this._Queryable;
            }
        }

        protected virtual ObjectQuery<Entity> ObjectQuery
        {
            get;
            set;
        }

        /// <summary>
        /// 在查询中，将关联对象一并取出。
        /// </summary>
        protected virtual IQueryable<IEntity> TryIncludes(ObjectQuery<Entity> query)
        {
            if (this.Includes.Length > 0)
            {
                foreach (var include in Includes)
                {
                    query = query.Include(include);
                }

            }


            return this.Condition == null ? query : query.Where(this.Condition);
        }

        /// <summary>
        /// 支持语法 Entity SQL Language http://msdn.microsoft.com/en-us/library/bb387105.aspx
        /// </summary>
        /// <param name="predicate"></param>
        public virtual void WithWhere(string predicate)
        {
            if (string.IsNullOrWhiteSpace(predicate))
            {
                this.ObjectQuery = this.Table;
            }
            else
            {
                this.ObjectQuery = this.Table.Where(predicate);
            }

            this._Queryable = null;
        }
    }
}
